<?php

class GIFReader {
var $BUF = '';
var $IMGS = array();
function GIFReader(){
}
function load($src,$mod = 'url'){
if($mod == 'url'){
$this->BUF = file_get_contents($src);
}else{
$this->BUF = $src;
}
$this->IMGS = array('info'=>array(),'frames'=>array());
$this->IMGS['info']['Loops'] = -1;
$this->IMGS['info']['UsesBkBuffer'] = false;
$this->IMGS['info']['Version'] = substr($this->BUF,0,6);
$this->IMGS['info']['HdrOffset'] = 0;
$this->IMGS['info']['Width'] = ord(substr($this->BUF,6,2));
$this->IMGS['info']['Height'] = ord(substr($this->BUF,8,2));
$gByte = ord($this->BUF{10});
$this->IMGS['info']['gTableUsed'] = $this->DoBitwise($gByte,0x80);
$this->IMGS['info']['gTableCount'] = $this->DoBitwise($gByte,0x07);
if($this->IMGS['info']['gTableUsed']){
$this->IMGS['info']['BkgColor'] = ord($this->BUF{11});
$this->ColorFromTable(0xE,$this->IMGS['info']['BkgColor'],$this->IMGS['info']['gTableCount']);
if($this->IMGS['info']['BkgColor'] <0)$this->IMGS['info']['BkgColor'] = 0;
$seek = 0xE +3 * (2 <<$this->IMGS['info']['gTableCount']) -1;
}else{
$seek = 13;
$this->IMGS['info']['BkgColor'] = 0;
$this->IMGS['info']['gTableCount'] = 0;
}
$fColor = -1;
$tmp = array();
while(true){
switch (ord($this->BUF{$seek})){
case 0:
$seek ++;
break;
case 33:
$seek ++;
switch (ord($this->BUF{$seek})){
case 255:
$seek ++;
if(count($this->IMGS['frames']) == 0){
$gByte = ord($this->BUF{$seek});
$seek ++;
$gifString = strtoupper(substr($this->BUF,$seek,8));
$seek += 8;
if($gifString == 'NETSCAPE'){
$seek += 3;
$gByte = ord($this->BUF{$seek});
$seek ++;
if($gByte == 3){
$seek ++;
$this->IMGS['info']['Loops'] = ord(substr($this->BUF,$seek,2));
$seek += 2;
if($this->IMGS['info']['Loops'] <1)$this->IMGS['info']['Loops'] = 0;
}else{
}
}else{
$seek += 3;
}
}
$gByte = ord($this->BUF{$seek});
$seek ++;
while($gByte >0){
$seek += $gByte;
$gByte = ord($this->BUF{$seek});
$seek ++;
}
break;
case 254:
$seek ++;
$gByte = ord($this->BUF{$seek});
$seek ++;
while($gByte >0){
$seek += $gByte;
$gByte = ord($this->BUF{$seek});
$seek ++;
}
break;
case 249:
$seek ++;
if($this->IMGS['info']['HdrOffset'] == 0)$this->IMGS['info']['HdrOffset'] = $seek -1;
$tmp['byteOffset(Begin)'] = $seek;
$seek += 1;
$gByte = ord($this->BUF{$seek});
$seek ++;
$tmp['FrameDisposal'] = $this->DoBitwise($gByte,0x1C);
if($tmp['FrameDisposal'] == 3)$this->IMGS['info']['UsesBkBuffer'] = True;
$tmp['isTransparent'] = $this->DoBitwise($gByte,0x01);
$tmp['frameDelay'] = ord(substr($this->BUF,$seek,2));
$seek += 2;
if($tmp['isTransparent']){
$fColor = ord($this->BUF{$seek});
$seek ++;
}
$seek += $tmp['isTransparent'];
break;
case 1:
$seek ++;
$gByte = ord($this->BUF{$seek});
$seek ++;
while($gByte >0){
$seek += $gByte;
$gByte = ord($this->BUF{$seek});
$seek ++;
}
break;
default:
$seek ++;
$gByte = ord($this->BUF{$seek});
$seek ++;
while($gByte >0){
$seek += $gByte;
$gByte = ord($this->BUF{$seek});
$seek ++;
}
break;
}
break;
case 44:
$seek ++;
if($this->IMGS['info']['HdrOffset'] == 0){
$tmp['byteOffset(Begin)'] = $seek;
$this->IMGS['info']['HdrOffset'] = $seek -1;
}
$tmp['FrameLeft'] = ord(substr($this->BUF,$seek,2));
$seek += 2;
$tmp['FrameTop'] = ord(substr($this->BUF,$seek,2));
$seek += 2;
$tmp['FrameWidth'] = ord(substr($this->BUF,$seek,2));
$seek += 2;
$tmp['FrameHeight'] = ord(substr($this->BUF,$seek,2));
$seek += 2;
$gByte = ord($this->BUF{$seek});
$seek ++;
$tmp['lTableUsed'] = $this->DoBitwise($gByte,0x80);
if($tmp['lTableUsed']){
$tmp['lTableCount'] = $this->DoBitwise($gByte,0x07);
$lTableLoc = $seek;
$seek += 3 * (2 <<$tmp['lTableCount']);
}else{
$tmp['lTableCount'] = 0;
$seek ++;
}
if($tmp['isTransparent']){
if($this->IMGS['info']['gTableCount']){
$this->ColorFromTable(0xE,$fColor,$this->IMGS['info']['gTableCount']);
}elseif($tmp['lTableCount']){
$this->ColorFromTable($lTableLoc,$fColor,$tmp['lTableCount']);
}
$tmp['FrameTransparentColor'] = $fColor;
}else{
$tmp['FrameTransparentColor'] = -1;
}
$gByte = ord($this->BUF{$seek});
$seek ++;
while($gByte >0){
$seek += $gByte;
$gByte = ord($this->BUF{$seek});
$seek ++;
}
$tmp['byteOffset(End)'] = $seek;
array_push($this->IMGS['frames'],$tmp);
$tmp = array();
$fColor = -1;
break;
case 59:
break(2);
default:
$seek ++;
$gByte = ord($this->BUF{$seek});
$seek ++;
while($gByte >0){
$seek += $gByte;
$gByte = ord($this->BUF{$seek});
$seek ++;
}
break;
}
}
}
function getgif($i){
if(!isset($this->IMGS['frames'][$i]['byteOffset(Begin)']))return '';
$pos1 = $this->IMGS['frames'][$i]['byteOffset(Begin)'];
$pos2 = $this->IMGS['frames'][$i]['byteOffset(End)'];
return $this->getheader().substr($this->BUF,$pos1,$pos2 -$pos1).';';
}
function fixgif($i,$mode = 1){
if(!isset($this->IMGS['frames'][$i]['byteOffset(Begin)']))return false;
$src = $this->getgif($i);
$sim = imagecreatefromstring($src);
if($mode === 0)return $sim;
if($sim){
$dim = imagecreate($this->IMGS['info']['Width'],$this->IMGS['info']['Height']);
if($this->IMGS['info']['BkgColor'] >-1){
imagefilledrectangle($dim,0,0,$this->IMGS['info']['Width'],$this->IMGS['info']['Height'],$this->getcolor($dim,dechex($this->IMGS['info']['BkgColor'])));
}else{
imagecolortransparent($dim,$this->getcolor($dim));
}
imagecopyresampled($dim,$sim,$this->IMGS['frames'][$i]['FrameLeft'],$this->IMGS['frames'][$i]['FrameTop'],0,0,$this->IMGS['frames'][$i]['FrameWidth'],$this->IMGS['frames'][$i]['FrameHeight'],$this->IMGS['frames'][$i]['FrameWidth'],$this->IMGS['frames'][$i]['FrameHeight']);
imagedestroy($sim);
if($this->IMGS['info']['BkgColor'] == -1)imagesavealpha($dim,true);
return $dim;
}
return false;
}
function getsrc($im,$mode = 0){
if($mode === 0){
$tmp = explode(' ',microtime());
$tmp[0] = $tmp[0] * 10000000;
$tmp = $tmp[0] +$tmp[1];
imagegif($im,$tmp);
$src = file_get_contents($tmp);
@unlink($tmp);
}else{
ob_start();
imagegif($im);
$src = ob_get_clean();
ob_end_clean();
}
return $src;
}
function getcolor(&$im,$color = '#000000'){
if($color[0] == '#')$color = substr($color,1);
if(strlen($color) == 6)list($r,$g,$b) = array($color[0].$color[1],$color[2].$color[3],$color[4].$color[5]);
elseif(strlen($color) == 3)list($r,$g,$b) = array($color[0].$color[0],$color[1].$color[1],$color[2].$color[2]);
else return false;
return imagecolorallocate($im,hexdec($r),hexdec($g),hexdec($b));
}
function getheader(){
if(!isset($this->IMGS['frames'][0]['byteOffset(Begin)']))return '';
$pos = $this->IMGS['frames'][0]['byteOffset(Begin)'];
return substr($this->BUF,0,$pos);
}
function savegif($src,$path = '',$mode = 'w+'){
if(empty($src))return false;
$fso = @fopen($path,$mode);
@fwrite($fso,$src);
@fclose($fso);
return true;
}
function DoBitwise($lFlags,$lMask){
if($lMask >0){
$result = ($lFlags &$lMask);
while(($lMask &1) == 0){
$lMask = floor($lMask / 2);
$result = floor($result / 2);
}
}
return $result;
}
function ColorFromTable($seekIdx,&$tIndex,$nrColors) {
if($tIndex <0)return ;
if($tIndex * 3 >(2 <<($nrColors * 3)) -2){
$tIndex = 0;
return ;
}
$tIndex = ord(substr($this->BUF,$seekIdx +$tIndex * 3,3));
$tIndex = $tIndex |( $tIndex <<8 ) |( $tIndex <<16 );
}
}

?>